package com.mxpio.erp.inventory.controller;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.mxpio.erp.common.ItemGroupUtil;
import com.mxpio.erp.common.inventory.entity.*;
import com.mxpio.erp.common.inventory.service.*;
import com.mxpio.erp.common.technology.entity.ItemGroup;
import com.mxpio.erp.common.technology.service.ItemGroupService;
import com.mxpioframework.jpa.query.Operator;
import com.mxpioframework.jpa.query.SimpleCriterion;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.query.Criteria;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;

@Tag(name = "InvFlowController", description = "库存流水接口")
@RestController
@RequestMapping("/erp/inventory/flow/")
public class InvFlowController {
	
	@Autowired
	private InvFlowService invFlowSerivce;
	
	@Autowired
	private VInvLotStockService vInvLotStockService;

	@Autowired
	private VInvStockHoldService vInvStockHoldService;

	@Autowired
	private VItemConsumedByDeptPerMonthService vItemConsumedByDeptPerMonthService;

	@Autowired
	private VItemShortageWarningService vItemShortageWarningService;

	@Autowired
	private VItemConsumedByDeptPerDayService vItemConsumedByDeptPerDayService;

	@Autowired
	private ItemGroupService itemGroupsSerivce;

	@Autowired
	private VInvFlowService vInvFlowService;//vInvFlow视图service

	@Autowired
	private VInvStockService vInvStockService;

	@Autowired
	private VInvFlowBusiDetailInService vInvFlowBusiDetailInService;
	@Autowired
	private VInvFlowBusiDetailOutWithoutSaleService vInvFlowBusiDetailOutWithoutSaleService;
	@Autowired
	private VInvFlowBusiDetailSaleOutService vInvFlowBusiDetailSaleOutService;
	@Autowired
	private VInvFlowBusiDetailScrapService vInvFlowBusiDetailScrapService;
	@Autowired
	private VInvLotStockWithSoaHoldService vInvLotStockWithSoaHoldService;
	@GetMapping("list")
	@Operation(summary = "库存流水列表", description = "获取库存流水列表", method = "GET")
	public Result<List<VInvFlow>> list(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvFlow> invFlows = vInvFlowService.list(criteria);
		return Result.OK(invFlows);
	}
	
	@GetMapping("page")
	@Operation(summary = "库存流水列表", description = "获取库存流水列表", method = "GET")
	public Result<Page<VInvFlow>> page(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		//处理有物料组检索条件时，加载子孙节点组数据逻辑
		List<Object> criterions = criteria.getCriterions();
		List<String> groupCodes = new ArrayList<>();
		if (!criterions.isEmpty()){
			Iterator<Object> iterator = criterions.iterator();
			Criteria c = Criteria.create();
			List<ItemGroup> itemGroups = itemGroupsSerivce.tree(ItemGroup.class, c);
			while(iterator.hasNext()){
				Object next = iterator.next();
				if (next instanceof SimpleCriterion){
					SimpleCriterion simpleCriterion = (SimpleCriterion)next;
					if (StringUtils.equals(simpleCriterion.getFieldName(),"itemGroupCode")){
						String value = (String) simpleCriterion.getValue();
						if (itemGroups.size()>0){
							ItemGroup itemGroupFromList = ItemGroupUtil.getItemGroupFromList(itemGroups, value);
							ItemGroupUtil.getAllGroupCodeFromItemGroup(groupCodes,itemGroupFromList);
						}
						if (groupCodes.size()>0){
							iterator.remove();
						}
						break;
					}
				}
			}
		}
		if (groupCodes.size()>0){
			criteria.addCriterion("itemGroupCode", Operator.IN,groupCodes);
		}

		Page<VInvFlow> page = vInvFlowService.listPage(pageAble, criteria);
		return Result.OK(page);
	}
	
	@GetMapping("lot/sum/list")
	@Operation(summary = "批次库存汇总表", description = "批次库存汇总表", method = "GET")
	public Result<List<VInvLotStock>> sumListByLot(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvLotStock> invFlows = vInvLotStockService.listByLot(criteria);
		return Result.OK(invFlows);
	}
	
	@GetMapping("lot/sum/page")
	@Operation(summary = "批次库存汇总表（分页）", description = "批次库存汇总表（分页）", method = "GET")
	public Result<Page<VInvLotStock>> sumPageByLot(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		//处理有物料组检索条件时，加载子孙节点组数据逻辑
		List<Object> criterions = criteria.getCriterions();
		List<String> groupCodes = new ArrayList<>();
		if (!criterions.isEmpty()){
			Iterator<Object> iterator = criterions.iterator();
			Criteria c = Criteria.create();
			List<ItemGroup> itemGroups = itemGroupsSerivce.tree(ItemGroup.class, c);
			while(iterator.hasNext()){
				Object next = iterator.next();
				if (next instanceof SimpleCriterion){
					SimpleCriterion simpleCriterion = (SimpleCriterion)next;
					if (StringUtils.equals(simpleCriterion.getFieldName(),"itemGroupCode")){
						String value = (String) simpleCriterion.getValue();
						if (itemGroups.size()>0){
							ItemGroup itemGroupFromList = ItemGroupUtil.getItemGroupFromList(itemGroups, value);
							ItemGroupUtil.getAllGroupCodeFromItemGroup(groupCodes,itemGroupFromList);
						}
						if (groupCodes.size()>0){
							iterator.remove();
						}
						break;
					}
				}
			}
		}
		if (groupCodes.size()>0){
			criteria.addCriterion("itemGroupCode", Operator.IN,groupCodes);
		}

		Page<VInvLotStock> page = vInvLotStockService.listPageByLot(pageAble, criteria);
		return Result.OK(page);
	}
	
	@GetMapping("sum/list")
	@Operation(summary = "库存汇总表", description = "库存汇总表", method = "GET")
	public Result<List<VInvStock>> sumList(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvStock> invFlows = vInvStockService.list(criteria);
		return Result.OK(invFlows);
	}
	
	@GetMapping("sum/page")
	@Operation(summary = "库存汇总表（实时库存）（分页）", description = "库存汇总表（实时库存）（分页）", method = "GET")
	public Result<Page<VInvStock>> sumPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		//处理有物料组检索条件时，加载子孙节点组数据逻辑
		List<Object> criterions = criteria.getCriterions();
		List<String> groupCodes = new ArrayList<>();
		if (!criterions.isEmpty()){
			Iterator<Object> iterator = criterions.iterator();
			Criteria c = Criteria.create();
			List<ItemGroup> itemGroups = itemGroupsSerivce.tree(ItemGroup.class, c);
			while(iterator.hasNext()){
				Object next = iterator.next();
				if (next instanceof SimpleCriterion){
					SimpleCriterion simpleCriterion = (SimpleCriterion)next;
					if (StringUtils.equals(simpleCriterion.getFieldName(),"itemGroupCode")){
						String value = (String) simpleCriterion.getValue();
						if (itemGroups.size()>0){
							ItemGroup itemGroupFromList = ItemGroupUtil.getItemGroupFromList(itemGroups, value);
							ItemGroupUtil.getAllGroupCodeFromItemGroup(groupCodes,itemGroupFromList);
						}
						if (groupCodes.size()>0){
							iterator.remove();
						}
						break;
					}
				}
			}
		}
		if (groupCodes.size()>0){
			criteria.addCriterion("itemGroupCode", Operator.IN,groupCodes);
		}
		Page<VInvStock> page = vInvStockService.listPage(pageAble, criteria);
		return Result.OK("0",page);
	}
	
	@GetMapping("list/{id}")
	@Operation(summary = "根据id获取库存流水", description = "根据id获取库存流水", method = "GET")
	public Result<InvFlow> getById(@PathVariable(name = "id", required = true) String id) {
		InvFlow invFlow = invFlowSerivce.getById(InvFlow.class, id);
		return Result.OK(invFlow);
	}

	@GetMapping("hold/list")
	@Operation(summary = "实时库存(带占用)表", description = "实时库存(带占用)", method = "GET")
	public Result<List<VInvStockHold>> holdList(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvStockHold> list = vInvStockHoldService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("hold/page")
	@Operation(summary = "实时库存(带占用)表（分页）", description = "实时库存(带占用)表（分页）", method = "GET")
	public Result<Page<VInvStockHold>> holdPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VInvStockHold> page = vInvStockHoldService.listPage(pageAble, criteria);
		return Result.OK(page);
	}

	@GetMapping("itemConsumedByDeptPerMonth/list")
	@Operation(summary = "部门月度物资消耗明细", description = "部门月度物资消耗明细", method = "GET")
	public Result<List<VItemConsumedByDeptPerMonth>> itemConsumedByDeptPerMonthList(Criteria criteria) throws UnsupportedEncodingException {
		List<VItemConsumedByDeptPerMonth> list = vItemConsumedByDeptPerMonthService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("itemConsumedByDeptPerMonth/page")
	@Operation(summary = "部门月度物资消耗明细（分页）", description = "部门月度物资消耗明细（分页）", method = "GET")
	public Result<Page<VItemConsumedByDeptPerMonth>> itemConsumedByDeptPerMonthPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VItemConsumedByDeptPerMonth> page = vItemConsumedByDeptPerMonthService.listPage(pageAble, criteria);
		if (page.getContent().size()>0){
			VItemConsumedByDeptPerMonth vItemConsumedByDeptPerMonth = vItemConsumedByDeptPerMonthService.listPageSumFee(criteria);
			return Result.OK(vItemConsumedByDeptPerMonth.getFee().toPlainString(),page);
		}
		return Result.OK("0",page);
	}

	@GetMapping("itemShortageWarning/list")
	@Operation(summary = "库存安全数量预警明细", description = "库存安全数量预警明细", method = "GET")
	public Result<List<VItemShortageWarning>> itemShortageWarningList(Criteria criteria) throws UnsupportedEncodingException {
		List<VItemShortageWarning> list = vItemShortageWarningService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("itemShortageWarning/page")
	@Operation(summary = "库存安全数量预警明细（分页）", description = "库存安全数量预警明细（分页）", method = "GET")
	public Result<Page<VItemShortageWarning>> itemShortageWarningPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VItemShortageWarning> page = vItemShortageWarningService.listPage(pageAble, criteria);
		return Result.OK(page);
	}

	@GetMapping("itemConsumedByDeptPerDay/list")
	@Operation(summary = "部门日度物资消耗明细", description = "部门日度物资消耗明细", method = "GET")
	public Result<List<VItemConsumedByDeptPerDay>> itemConsumedByDeptPerDayList(Criteria criteria) throws UnsupportedEncodingException {
		List<VItemConsumedByDeptPerDay> list = vItemConsumedByDeptPerDayService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("itemConsumedByDeptPerDay/page")
	@Operation(summary = "部门日度物资消耗明细（分页）", description = "部门日度物资消耗明细（分页）", method = "GET")
	public Result<Page<VItemConsumedByDeptPerDay>> itemConsumedByDeptPerDayPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VItemConsumedByDeptPerDay> page = vItemConsumedByDeptPerDayService.listPage(pageAble, criteria);
		if (page.getContent().size()>0){
			VItemConsumedByDeptPerDay vItemConsumedByDeptPerDay = vItemConsumedByDeptPerDayService.listPageSumFee(criteria);
			return Result.OK(vItemConsumedByDeptPerDay.getFee().toPlainString(),page);
		}
		return Result.OK("0",page);
	}


	@GetMapping("flowbusiin/list")
	@Operation(summary = "流水入库业务报表", description = "流水入库业务报表", method = "GET")
	public Result<List<VInvFlowBusiDetailIn>> vInvFlowBusiDetailInList(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvFlowBusiDetailIn> list = vInvFlowBusiDetailInService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("flowbusiin/page")
	@Operation(summary = "流水入库业务报表（分页）", description = "流水入库业务报表（分页）", method = "GET")
	public Result<Page<VInvFlowBusiDetailIn>> vInvFlowBusiDetailInPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VInvFlowBusiDetailIn> page = vInvFlowBusiDetailInService.listPage(pageAble, criteria);
		return Result.OK(page);
	}

	@GetMapping("flowoutwithoutsale/list")
	@Operation(summary = "流水出库业务报表，不包含销售出库", description = "流水出库业务报表，不包含销售出库", method = "GET")
	public Result<List<VInvFlowBusiDetailOutWithoutSale>> vInvFlowBusiDetailOutWithoutSaleList(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvFlowBusiDetailOutWithoutSale> list = vInvFlowBusiDetailOutWithoutSaleService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("flowoutwithoutsale/page")
	@Operation(summary = "流水出库业务报表，不包含销售出库（分页）", description = "流水出库业务报表，不包含销售出库（分页）", method = "GET")
	public Result<Page<VInvFlowBusiDetailOutWithoutSale>> vInvFlowBusiDetailOutWithoutSalePage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VInvFlowBusiDetailOutWithoutSale> page = vInvFlowBusiDetailOutWithoutSaleService.listPage(pageAble, criteria);
		return Result.OK(page);
	}

	@GetMapping("flowsaleout/list")
	@Operation(summary = "流水出库业务报表，销售出库", description = "流水出库业务报表，销售出库", method = "GET")
	public Result<List<VInvFlowBusiDetailSaleOut>> vInvFlowBusiDetailSaleOutList(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvFlowBusiDetailSaleOut> list = vInvFlowBusiDetailSaleOutService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("flowsaleout/page")
	@Operation(summary = "流水出库业务报表，销售出库（分页）", description = "流水出库业务报表，销售出库（分页）", method = "GET")
	public Result<Page<VInvFlowBusiDetailSaleOut>> vInvFlowBusiDetailSaleOutPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VInvFlowBusiDetailSaleOut> page = vInvFlowBusiDetailSaleOutService.listPage(pageAble, criteria);
		return Result.OK(page);
	}


	@GetMapping("flowscrap/list")
	@Operation(summary = "报废申请业务报表", description = "报废申请业务报表", method = "GET")
	public Result<List<VInvFlowBusiDetailScrap>> vInvFlowBusiDetailScrapList(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvFlowBusiDetailScrap> list = vInvFlowBusiDetailScrapService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("flowscrap/page")
	@Operation(summary = "报废申请业务报表（分页）", description = "报废申请业务报表（分页）", method = "GET")
	public Result<Page<VInvFlowBusiDetailScrap>> vInvFlowBusiDetailScrapPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VInvFlowBusiDetailScrap> page = vInvFlowBusiDetailScrapService.listPage(pageAble, criteria);
		return Result.OK(page);
	}

	@GetMapping("soahold/list")
	@Operation(summary = "批次库存（报废申请占用统计）表", description = "批次库存（报废申请占用统计）表", method = "GET")
	public Result<List<VInvLotStockWithSoaHold>> soaHoldList(Criteria criteria) throws UnsupportedEncodingException {
		List<VInvLotStockWithSoaHold> list = vInvLotStockWithSoaHoldService.list(criteria);
		return Result.OK(list);
	}

	@GetMapping("soahold/page")
	@Operation(summary = "批次库存（报废申请占用统计）表", description = "批次库存（报废申请占用统计）表", method = "GET")
	public Result<Page<VInvLotStockWithSoaHold>> soaHoldPage(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
		Pageable pageAble = PageRequest.of(pageNo-1, pageSize);
		Page<VInvLotStockWithSoaHold> page = vInvLotStockWithSoaHoldService.listPage(pageAble, criteria);
		return Result.OK(page);
	}


}
